/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package heartinjava;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author TIENDAT
 */

public class Server implements Runnable {
    
    private XLThread clients[] = new XLThread[60];
    public ServerSocket server = null;
    private Thread      thread = null;
    private int         countClient = 0;
    public boolean      isConnect ;
    HeartInJava         m_Main;
    private InetAddress ipAddress;
    
    public Server(int port, final HeartInJava m_main) 
    {
        try {
            System.out.println("Đang kết nối đến port " + port + ", vui lòng chờ  ...");
            ipAddress =InetAddress.getLocalHost();
            //server = new ServerSocket(port);
            server = new ServerSocket(port,0, ipAddress);
            System.out.println("Server đã mở: " + server);
            m_Main = m_main;
            start();
            isConnect = true;
        } catch (IOException ioe) {
            isConnect= false;
            System.out.println("Không thể kết nối đến port " + port + ": " + ioe.getMessage());
        }
    }

    public boolean IsExchanged()
    {
        if (countClient==3)
        {
           return (clients[0].getEndExchange()&&clients[1].getEndExchange()&&clients[2].getEndExchange()); 
        }
        return false;
    }

    public ArrayList<Integer> getCardExchange(int index)
    {
        return clients[index].getCardChange();
    }
    
    public void run() 
    {
        while (thread != null) {
            try {
                System.out.println("Waiting for a client ...");
                addThread(server.accept());
            } catch (IOException ioe) {
                System.out.println("Server accept error: " + ioe);
                stop();
            }
        }
    }

    public void start() 
    {
        if (thread == null) 
        {
            thread = new Thread(this);
            thread.start();
        }
    }

    public void stop() 
    {
        try {
            isConnect = false;
            if (thread != null) 
            {
                thread.stop();
                thread = null;
            }
            if (server != null) 
            {
                server.close();
            }
        } catch (IOException ex) {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private int findClient(int ID) 
    {
        for (int i = 0; i < getClientCount(); i++) 
        {
            if (getClients()[i].getID() == ID) 
            {
                return i;
            }
        }
        return -1;
    }

    public synchronized void SendToAllClient(String input) 
    {
        for (int i = 0; i < countClient; i++) 
        {
            if (input.equals(".bye")) 
            {
                getClients()[i].send(".bye");
                removeAt(i);
            }
            else 
            {
                getClients()[i].send(input);
            }
        }
    }

    public synchronized void SendToClient(int index, String input) 
    {
        if (input.equals(".bye")) 
        {
            getClients()[index].send(".bye");
            removeAt(index);
        }
        else 
        {
            getClients()[index].send(input);
        }
    }

    public synchronized void removeAt(int index) 
    {
        int pos = index;
        if (pos >= 0) 
        {
            XLThread toTerminate = getClients()[pos];
            System.out.println("Removing client thread " + index + " at " + pos);
            if (pos < getClientCount() - 1) 
            {
                for (int i = pos + 1; i < getClientCount(); i++) 
                {
                    getClients()[i - 1] = getClients()[i];
                }
            }
            setClientCount(getClientCount() - 1);
            try {
                toTerminate.close();
            } catch (IOException ioe) {
                System.out.println("Error closing thread: " + ioe);
            }
            toTerminate.stop();
        }
    }

    public synchronized void handle(int ID, String input) 
    {
        System.out.println("Client send : " + input);
        if (input.equals(".bye")) {
            getClients()[findClient(ID)].send(".bye");
            remove(ID);
        }
        else if(input.equals("test")) 
        {
            getClients()[findClient(ID)].send(".bye");
            remove(ID);
        }
        else 
        {
            m_Main.ThongDiepTuClient(input);          
        }
    }

    public synchronized void remove(int ID) 
    {
        int pos = findClient(ID);
        if (pos >= 0) 
        {
            XLThread toTerminate = getClients()[pos];
            System.out.println("Removing client thread " + ID + " at " + pos);
            if (pos < getClientCount() - 1) 
            {
                for (int i = pos + 1; i < getClientCount(); i++) 
                {
                    getClients()[i - 1] = getClients()[i];
                }
            }
            countClient --;
            try {
                toTerminate.close();
            } catch (IOException ioe) {
                System.out.println("Error closing thread: " + ioe);
            }
            toTerminate.stop();
        }
    }

    private void addThread(Socket socket) 
    {
        if (getClientCount() < getClients().length) 
        {
            System.out.println("Client accepted: " + socket);
            getClients()[getClientCount()] = new XLThread(this, socket);
            try {
                getClients()[getClientCount()].open();
                getClients()[getClientCount()].start();
                countClient ++;
            } catch (Exception ioe) {
                System.out.println("Error opening thread: " + ioe);
            }
        } else {
            System.out.println("Client refused: maximum " + getClients().length + " reached.");
        }
    }

    public int getClientCount() 
    {
        return countClient;
    }

    public void setClientCount(int clientCount) 
    {
        this.countClient = clientCount;
    }

    public XLThread[] getClients() 
    {
        return clients;
    }

   
    public void setClients(XLThread[] clients) 
    {
        this.clients = clients;
    }

    public InetAddress getIpAddress() 
    {
        return ipAddress;
    }
    
    public void setIpAddress(InetAddress ipAddress) 
    {
        this.ipAddress = ipAddress;
    }
}
